(* DONT_TOUCH = "TRUE" *)
module IIR_single_stage_dsp #(
    parameter datin_width = 12,         // 输入数据位宽
    parameter daout_width = 12,         // 输出数据位宽
    parameter coeffct_width = 20,       // 系数位宽（含符号位）
    parameter b0 = 'd21,
    parameter b1 = -'d24,
    parameter b2 = 'd21,
    parameter a0 = 'd2048,
    parameter a1 = -'d3335,
    parameter a2 = 'd1370
)(
    input  signed [datin_width-1:0] Xin,
    input  signed [datin_width-1:0] Xin1,
    input  signed [datin_width-1:0] Xin2,
    input  signed [datin_width-1:0] Yin1,
    input  signed [datin_width-1:0] Yin2,
    output signed [datin_width-1:0] Yout
);

    wire signed [datin_width + coeffct_width - 1:0] XMult0, XMult1, XMult2;
    wire signed [daout_width + coeffct_width - 1:0] YMult1, YMult2;
    wire signed [datin_width + coeffct_width - 1:0] Xout;
    wire signed [daout_width + coeffct_width:0] Ysum;
    wire signed [daout_width + coeffct_width:0] Ydiv;

    function integer clogb2 (input integer depth);
		begin
			for (clogb2=0; depth>0; clogb2=clogb2+1) 
				depth = depth >>1;                          
		end
	endfunction

    // 输入乘以零点系数
    (* use_dsp48 = "yes" *) assign XMult0 = Xin  * b0;
    (* use_dsp48 = "yes" *) assign XMult1 = Xin1 * b1;
    (* use_dsp48 = "yes" *) assign XMult2 = Xin2 * b2;
    (* use_dsp48 = "yes" *) assign Xout   = XMult0 + XMult1 + XMult2;

    // 输出乘以极点系数
    (* use_dsp48 = "yes" *) assign YMult1 = Yin1 * a1;
    (* use_dsp48 = "yes" *) assign YMult2 = Yin2 * a2;

    // 加法和归一化
    (* use_dsp48 = "yes" *) assign Ysum = Xout - YMult1 - YMult2;

    // 系数a0为定值，用作除法因子（通常是2^N）
    assign Ydiv = Ysum >>> clogb2(a0) - 1;

    // 输出截断
    assign Yout = Ydiv[daout_width-1:0];

endmodule
